/**
 * 
 */
package org.gas.barapraja.db.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.transaction.annotation.Transactional;

/**
 * @author gilang
 *
 */
public abstract class GasEntityDao<E, ID extends Serializable> implements EntityDao<E, ID> {
	
	protected Class<E> entityClass;
	
	@PersistenceContext
	protected EntityManager entityManager;
	
	@SuppressWarnings("unchecked")
	public GasEntityDao() {
		ParameterizedType type=(ParameterizedType) getClass().getGenericSuperclass();
		entityClass=(Class<E>) type.getActualTypeArguments()[0];
	}

	/* (non-Javadoc)
	 * @see org.gas.barapraja.db.dao.EntityDao#persist(java.lang.Object)
	 */
	@Transactional
	public void persist(E entity) {
		entityManager.persist(entity);
	}

	/* (non-Javadoc)
	 * @see org.gas.barapraja.db.dao.EntityDao#remove(java.lang.Object)
	 */
	@Transactional
	public void remove(E entity) {
		if(entityManager.contains(entity)){
			entityManager.remove(entity);
		}else{
			E attached=entityManager.merge(entity);
			entityManager.remove(attached);
		}
	}

	/* (non-Javadoc)
	 * @see org.gas.barapraja.db.dao.EntityDao#findAll()
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public Collection<E> findAll() {
		Query q=entityManager.createQuery("select a from "+entityClass.getSimpleName()+" a");
		return q.getResultList();
	}

	/* (non-Javadoc)
	 * @see org.gas.barapraja.db.dao.EntityDao#find(java.io.Serializable)
	 */
	@Transactional(readOnly=true)
	public E find(ID id) {
		return entityManager.find(entityClass, id);
	}

	/* (non-Javadoc)
	 * @see org.gas.barapraja.db.dao.EntityDao#update(java.lang.Object)
	 */
	@Transactional
	public E update(E entity) {
		E merged=entityManager.merge(entity);
		entityManager.flush();
		return merged;
	}
	
	
	

}
